package trab4;

import java.awt.*;

import sim.core.*;
import trab4.rpc.* ;
import trab4.grid.*;
import trab4.persistence.*;
import trab4.transactions.*;
import trab4.transactions.two_phase_commit.*;

public class Server extends Node {

	final public int sid ;

	public Grid grid ;
	
	private Server_2PC_Stub tpcStub ;
	private ServerTransactionStub stub ;
	private dTransactionManager<GridOperations> tm ;
	
	public Server() {
		super();
		grid = new Grid( 30, 30 ) ;	
		sid = ServerDB.store( this ) ;
		tm = new dTransactionManager<GridOperations>( this ) ;
		stub = new ServerTransactionStub( this.endpoint, tm) ;
		tpcStub = new Server_2PC_Stub( this.endpoint, tm, tm ) ;
		
		// without two phase commit
		Naming.rebindServer("//" + sid, stub ) ;
		super.setMessageHandler( stub ) ;
		
		// Code also needed when implementing the two phase commit protocol...
		Naming.rebindServer("//" + sid + "/2pc", tpcStub ) ;
		super.setMessageHandler( tpcStub ) ;
	}
	
	public void onReboot() {
		if (Main.DEBUG) System.err.println("############################################################") ;
		if (Main.DEBUG) System.err.println("Server:" + sid + " is online after crashing and rebooting...") ;
		if (Main.DEBUG) System.err.println("############################################################") ;
		tm = new dTransactionManager<GridOperations>( this ) ;
		stub = new ServerTransactionStub( this.endpoint, tm) ;
		tpcStub = new Server_2PC_Stub( this.endpoint, tm, tm ) ;
		
		// without two phase commit
		Naming.rebindServer("//" + sid, stub ) ;
		super.setMessageHandler( stub );
		
		// Code also needed when implementing the two phase commit protocol...
		Naming.rebindServer("//" + sid + "/2pc", tpcStub );
		super.setMessageHandler( tpcStub );
		
		Storage.load( this, "grid" ) ;
		if (Main.DEBUG) System.err.println("Loaded old grid from persistent storage...") ;
	}
		
	public void crash() {
    	super.putOffline();
    	Scheduler.cancelAll( this ) ; 
    	if (Main.DEBUG) System.err.println("############################################################") ;
    	if (Main.DEBUG) System.err.println("Node:" + key + " is online after crashing and rebooting...") ;
    	if (Main.DEBUG) System.err.println("############################################################") ;
    	new Task( null, 20 + 80 * Simulation.rg.nextDouble()) {
    		public void run() {
    			reboot() ;
    		}
    	} ;
    }
    
	public void init() {
		
		new PeriodicTask(5, 60.0) {
			public void run() {
				if (Main.DEBUG) System.out.println("Server: " + sid + " [Saving state...]") ;
				Storage.save( Server.this, "grid", grid ) ;
			}
		} ;
	}
	
    private void reboot() {
    	endpoint = endpoint.replace() ;
    	this.onReboot() ;
    }
	//--------------------------------------------------------------------------------------------------------------	
	// Displays the committed grid
	synchronized public void display(Graphics2D gu, Graphics2D gs) {
		try { tm.display(gu, gs) ; } catch( Exception x ) {}
	}
}
